use crate::{catcher::Catcher, com::Com, myerror::MyErrs};
use serde::{Deserialize, Serialize};
use std::{fs, path::PathBuf};
use log::*;
#[derive(Deserialize, Serialize)]
pub struct DataStoreConfig {
    uploader_ids: Vec<u64>,
    special_column_ids: Vec<u64>,
    //write a function that can mix two structs and get a group that need download
    pub articles_ids: Vec<u64>,
    pub max_download_thread: u64
}
pub struct DataStore {
    pub config: DataStoreConfig,
    pub catcher: Catcher
}


impl DataStore{
    pub fn new(path: &PathBuf) -> Result<Self, MyErrs>{
        info!("new DataStore inited");
        let string_json = fs::read_to_string(path)?;
        let config: DataStoreConfig = serde_json::from_str(&string_json)?;
        let mut catcher = Catcher::new(0);
        catcher.max_thread = config.max_download_thread;
        let tmp = Self {
            config,
            catcher
        };
        Ok(tmp)
    }
    /// return article ids
    pub fn update(&mut self) -> Result<Vec<u64>, MyErrs>{
        info!("DataStore update!");
        let mut result = Vec::new();
        for i in self.config.uploader_ids.iter() {
            self.catcher.run_com(Com::SetUID(*i as usize))?;
            //read to result
            result.append(&mut self.catcher.get_article_ids()?);
        }
        for i in self.config.special_column_ids.iter() {
            result.append(&mut Catcher::get_ar_ids_by_one_sp(&i)?);
        }
        Ok(result)
    }
    pub fn save(&self, path: &PathBuf) -> Result<(), MyErrs>{
        info!("DataStore has saved");
        fs::write(path, serde_json::to_string(&self.config)?)?;
        Ok(())
    }
    /// call it after updated and removed
    pub fn start_download(&mut self, need_update: Vec<u64>) -> Result<(), MyErrs>{
        self.catcher.push_to_download(need_update)?;
        self.catcher.start_download()?;
        Ok(())
    }
}
